package org.mozhu.mboot.core.web.freemarker;

import freemarker.ext.beans.BeanModel;
import freemarker.template.SimpleDate;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.List;

@SuppressWarnings("rawtypes")
public class DateTimeFormatMethod implements TemplateMethodModelEx {
    private final static Logger LOGGER = LoggerFactory.getLogger(DateTimeFormatMethod.class);
    private static final String EMPTY = "";
    private static final String DATE_TIME_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss";

    @Override
    public Object exec(List arguments) throws TemplateModelException {
        if (arguments.size() > 1) {
            Object object = arguments.get(0);
            return format(object, getPattern(arguments.get(1)));
        } else if (arguments.size() == 1) {
            return format(arguments.get(0), DATE_TIME_FORMAT_PATTERN);
        }
        return new TemplateModelException("at least one argument");
    }

    private String getPattern(Object object) {
        if (object instanceof SimpleScalar) {
            return ((SimpleScalar) object).getAsString();
        }
        return (String) object;
    }

    private Object format(Object object, String format) {
        if (object == null) {
            return EMPTY;
        } else if (object instanceof SimpleDate) {
            return DateFormatUtils.format(((SimpleDate) object).getAsDate(), format);
        } else if (object instanceof BeanModel) {
            return format(((BeanModel) object).getWrappedObject(), format);
        } else if (object instanceof Date) {
            return DateFormatUtils.format((Date) object, format);
        } else if (object instanceof java.sql.Date) {
            return DateFormatUtils.format(((java.sql.Date) object).getTime(), format);
        } else if (object instanceof LocalDate) {
            return ((LocalDate) object).toString(format);
        } else if (object instanceof LocalDateTime) {
            return ((LocalDateTime) object).toString(format);
        } else if ("EmptyStringAndSequenceAndHash".equals(object.getClass().getSimpleName())) {
            return EMPTY;
        } else {
            LOGGER.warn("not support argument type of [" + object.getClass() + "]");
            return EMPTY;
        }
    }
}
